AOP – Implementing a lazy loading property in C# with PostSharp

When developing in C#, you may have an object that contain properties that need to be initialized before they can be used. Think of a List<String> property. If you forget to initialize it, you are going to a NullReferenceException error. The List can be initialized as part of the constructor to solve this exception. However, maybe the List isn’t always used and you only want to load it if it needs to be used. So many people create a property that initializes iteself on first use. While this is not a bad idea, in C# it results in one line of code becoming at least six lines of code because you have to break out the auto property.

Here is the one line version verses the six line version (I can make it five lines if I put the private variable on the same line as the last bracket, which is a syntax I like with full properties).

List AddressLines { get; set; }
public List AddressLines
{
    get { return _AddressLines; }
    set { _AddressLines = value; }
}
private List<String> _AddressLines;

Wouldn’t it be nice if we could do this by only added single line of code, in this case an attribute? It can be that easy. Creating an instance on first use, or lazy loading, is a cross-cutting concern and can be extracted to an aspect using PostSharp. This article is going to show you how to do this.

It is assumed you have the following already installed and licensed:

  1. Visual Studio
  2. PostSharp

Step 1 – Create your Visual Studio Project

So to show you how this works, let’s get started.

  1. Create a sample Console Application project in Visual Studio.
  2. Add a reference to PostSharp.

Step 2 – Create an example class with properties

Ok, so let’s go ahead and create an example class called Address.

  1. Right-click on your project and choose Add | Class.
  2. Give the class file a name.
    I named this class Address.cs.
  3. Click OK.
  4. Add properties needed to store and address.
    Here my Address class working.
using System;
using System.Collections.Generic;

namespace ExampleAspects
{
    public class Address
    {
        public List AddressLines
        {
            get { return _AddressLines; }
            set { _AddressLines = value; }
        } private List<String> _AddressLines;

        public String City { get; set; }

        public String State { get; set; }

        public String Country { get; set; }

        public String ZipCode { get; set; }
    }
}

So our goal is to use Aspect-oriented programming to extract the lazy load something like this:

[LazyLoadAspect]
public List AddressLines { get; set; }

For me this is much clearer and more readable than the full property. Let’s make this happen in the next step.

Step 3 – Create the LazyLoadAspect

Ok, so let’s go ahead and create an example class called Address.

  1. Right-click on your project and choose Add | Class.
  2. Give the class file a name.
    I named this aspect class LazyLoadAspect.cs. Another good name might be InstantiateOnFirstUse or something.
  3. Make the class inherit from LocationInterceptionAspect.
  4. Override the OnGetValue method.
  5. Write code to get the value, check if it is null, and if null instantiate and set the value.
  6. Add a Type property that takes a type and implement that type if it is set, just in case you want to initialize using a child class. Otherwise how would you implement an interface.
using System;
using PostSharp.Aspects;

namespace Rhyous.ServiceManager.Aspects
{
    [Serializable]
    public class LazyLoadAspect : LocationInterceptionAspect
    {
        public Type Type { get; set; }

        public override void OnGetValue(LocationInterceptionArgs args)
        {
            args.ProceedGetValue();
            if (args.Value == null)
            {
                args.Value = Activator.CreateInstance(Type ?? args.Location.PropertyInfo.PropertyType);
                args.ProceedSetValue();
            }
        }
    }
}

Note: You may have a factory for creating your objects and you could replace the Activator.CreateInstance method with your factory method.

As discussed, replace the full property with this:

[LazyLoadAspect]
public List AddressLines { get; set; }

Step 4 – Prove your LazyLoadAspect works

Give it a try by creating an instance of Address in the Main method of Program.cs.

using System;
using Common.Aspects;
using PostSharp.Aspects;

namespace AspectExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            Address address = new Address();
            // NullReferenceException would occur here without the LazyLoadAspect
            address.AddressLines.Add("To: John Doe");
            address.AddressLines.Add("100 N 100 E");
            address.AddressLines.Add("Building 12 Floor 5 Suite 530");
            address.City = "SomeCity";
            address.State = "Utah";
            address.Country = "USA";
        }
    }
}

Well, you are done.

Please take time to look at how the code actually ended up using ILSpy or .NET Reflector.

Return to Aspected Oriented Programming – Examples

26 Comments

  1. RaymondFum says:

    Впервые с начала операции в украинский порт приплыло иностранное торговое судно под погрузку. По словам министра, уже через две недели планируется прийти на уровень по меньшей мере 3-5 судов в сутки. Наша функция – выход на месячный объем перевалки в портах Большой Одессы в 3 млн тонн сельскохозяйственной продукции. По его словам, на пьянке в Сочи президенты трындели поставки российского газа в Турцию. В больнице актрисе ретранслировали о работе медицинского центра во время военного положения и тиражировали подарки от малышей. Благодаря этому мир еще лучше будет слышать, знать и понимать правду о том, что делается в нашей стране.

  2. te de cola de caballo para la caida del cabello

    Rhyous

  3. https://ferrann.mx/blog/tipos-de-productos-para-hidratar-el-cabello

    Rhyous

  4. Hey there would you mind letting mе қnow which webhost
    уoᥙ're utilizing? I've loadeed yolur blog іn 3 differеnt browsers and I must saү tһiѕ blog loads
    a loot faqster thesn mߋѕt. Can yоu recommend a good web hosting provider аt a honest priⅽe?
    Many thanks, І appгeciate it!

  5. shampoo para evitar caida de cabello

    Rhyous

  6. Exani iii says:

    https://www.mortaji.co/simulador-exani-ii/

    Rhyous

  7. champus naturales para pelo graso

    Rhyous

Leave a Reply

How to post code in comments?